using System;
using MetaObjects.Contracts;
using Microsoft.SharePoint;

namespace MetaObjects.SharePoint
{
	public abstract class FieldBase<TField, TValue> : IMetaField<SPListItem, TValue>, IMetaFieldProvider<TField>
		where TField : SPField
	{
		object IEntity.Key { get { return InternalName; } }
		public string InternalName { get; private set; }
		public string DisplayName { get; set; }
		public string Description { get; set; }
		public bool Required { get; set; }
		public bool ReadOnly { get; set; }
		object IMetaField.DefaultValue
		{
			get { return DefaultValue; }
			set { DefaultValue = (TValue)value; }
		}
		public TValue DefaultValue { get; set; }

		Action<object, object> IMetaField.SetField { get { return (entity, value) => SetField((SPListItem)entity, (TValue)value); } }
		Func<object, object> IMetaField.GetField { get { return entity => GetField((SPListItem)entity); } }
		Action<object, TValue> IMetaField<TValue>.SetField { get { return (entity, value) => SetField((SPListItem)entity, value); } }
		Func<object, TValue> IMetaField<TValue>.GetField { get { return entity => GetField((SPListItem)entity); } }

		public abstract Action<SPListItem, TValue> SetField { get; }
		public abstract Func<SPListItem, TValue> GetField { get; }

		protected FieldBase() { }

		public FieldBase(TField field)
		{
			InternalName = field.InternalName;
			DisplayName = field.Title;
			Description = field.Description;
		}

		Func<object, IMetaField> IMetaFieldProvider.FieldFactory
		{
			get { return f => FieldFactory((TField)f); }
		}
		public abstract Func<TField, IMetaField> FieldFactory { get; }
	}
}